#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <assert.h>
#include <string.h>
#include <sys/wait.h>
#include <sys/types.h>


#define QUIT 0
#define LEFT "["
#define RIGHT "]"
#define LABEL "$"
#define LINE_SIZE 1024
#define DELIM " \t"
#define EXITCODE 111

char* argv[LINE_SIZE];
extern char** environ;
char pwd[LINE_SIZE];
char commandline[LINE_SIZE];
int lastcode = 0;
const char* getusername()
{
    return getenv("USER");
}

const char* gethostname()
{
    return getenv("HOSTNAME");
}

void getpwd()
{
    getcwd(pwd,sizeof(pwd));
}

int splitstring(char cline[],char* _argv[])
{
    int i = 0;
    _argv[i++] = strtok(cline,DELIM);
    while(_argv[i++] = strtok(NULL,DELIM));
    return i-1;
}

void interact(char* cline,int size)
{
    getpwd();
    printf(LEFT"%s@%s %s"RIGHT""LABEL" ",getusername(),gethostname(),pwd);
    char* s = fgets(cline,size,stdin);
    assert(s);
    (void)s;
    //abcd\n\0
    cline[strlen(cline)-1]='\0';
}

int buildcommand(int _argc,char* _argv[])
{
    if(_argc == 2 && strcmp(_argv[0],"cd") == 0)
    {
        chdir(_argv[1]);
        getpwd();
        sprintf(getenv("PWD"),"%s",pwd);
        return 1;
    }
    else if(_argc == 2 && strcmp(_argv[0],"echo") == 0)
    {
        if(strcmp(_argv[1],"$?") == 0)
        {
            printf("%d\n",lastcode);
            lastcode = 0;
        }
        else if(*_argv[1] == '$')
        {
            char* val = getenv(_argv[1]+1);
            if(val)
                printf("%s\n",val);
        }
        else
        {
            printf("%s\n",_argv[1]);
        }
        return 1;

    }
    if(strcmp(_argv[0],"ls") == 0)
    {
        _argv[_argc++] = "--color";
        _argv[_argc] = NULL;
    }
    return 0;
}

void normalexcute(char* _argv[])
{
    pid_t id = fork();
    if(id < 0)
    {
        perror("fork");
        return;
    }
    else if(id == 0)
    {
        execvp(_argv[0],_argv);
        exit(EXITCODE);
    }
    else
    {
        int status = 0;
        pid_t rid = waitpid(id,&status,0);
        if(rid == id)
        {
            lastcode = WEXITSTATUS(status);
        }
    }
    
}
int main()
{
    //1.设置循环执行myshell
    while(!QUIT)
    {
        //2.读取命令行信息
        interact(commandline,sizeof(commandline));
        
        //3.拆解命令行信息为命令行参数
        int argc = splitstring(commandline,argv);
        if(argc == 0)
            continue;
        //4.内建命令处理
        int n = buildcommand(argc,argv);

        //5.普通命令执行
        if(!n) normalexcute(argv);

    }
    return 0;
}
